// 19.7 局部类
/**
 * 类可以定义在某个函数的内部，我们称这样的类为局部类（local class）。局部类定义的类型只在定义它的作用域内可见。和嵌套类不同，局部类的成员受到严格限制。
 * 局部类的所有成员（包括函数在内）都必须完整定义在类的内部。因此，局部类的作用与嵌套类相比相差很远。
 * 在实际编程的过程中，因为局部类的成员必须完整定义在类的内部，所以成员函数的复杂性不可能太高。局部类的成员函数一般只有几行代码，否则我们就很难读懂它了。
 * 类似的，在局部类中也不允许声明静态数据成员，因为我们没法定义这样的成员。
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy;
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <memory>
#include <new>
using namespace std;
#include <functional>
#include "../VisualStudio2012/15/Quote.h"
#include "../VisualStudio2012/12/TextQuery.h"
#include <tuple>
#include <bitset>
#include <regex>
#include <random>
#include <cmath>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <typeinfo>

int main()
{
    // 局部类不能使用函数作用域中的变量
    /*局部类对其外层作用域中名字的访问权限受到很多限制，局部类只能访问外层作用域定义的类型名、静态变量（参见6.1.1节，第185页）以及枚举成员。
        如果局部类定义在某个函数内部，则该函数的普通局部变量不能被该局部类使用：[插图][插图]
int a, val;
void foo(int val);
{
    static int si;
    enum Loc { a= 1024, b };
    // Bar是foo的局部类
    struct Bar {
        Loc locVal;            // 正确：使用一个局部类型名
        int barVal;
        void fooBar(Loc l = a) // 正确：默认实参是Loc::a
        {
            barVal = val;      // 错误：val是foo的局部变量
            barVal = ::val;    // 正确：使用一个全局对象
            barVal = si;       // 正确：使用一个静态局部对象
            locVal = b;        // 正确：使用一个枚举成员
        }
    };
    // ...
}
    */

    // 常规的访问保护规则对局部类同样适用
    /*外层函数对局部类的私有成员没有任何访问特权。当然，局部类可以将外层函数声明为友元；或者更常见的情况是局部类将其成员声明成公有的。在程序中有权访问局部类的代码非常有限。
        局部类已经封装在函数作用域中，通过信息隐藏进一步封装就显得没什么必要了。
    */

    // 局部类中的名字查找
    /*局部类内部的名字查找次序与其他类相似。在声明类的成员时，必须先确保用到的名字位于作用域中，然后再使用该名字。定义成员时用到的名字可以出现在类的任意位置。
        如果某个名字不是局部类的成员，则继续在外层函数作用域中查找；如果还没有找到，则在外层函数所在的作用域中查找。
    */

    // 嵌套的局部类
    /*可以在局部类的内部再嵌套一个类。此时，嵌套类的定义可以出现在局部类之外。不过，嵌套类必须定义在与局部类相同的作用域中。[插图]
void foo()
{
    class Bar {
    public:
        // ...
        class Nested; // 声明Nested类
    };
    // 定义Nested类
    class Bar::Nested {
        // ...
    };
}
      局部类内的嵌套类也是一个局部类，必须遵循局部类的各种规定。嵌套类的所有成员都必须定义在嵌套类内部。
    */

    return 0;
}